package com.young.ums.service.impl;

import com.young.common.exception.BaseException;
import com.young.common.util.CommonUtil;
import com.young.common.core.dal.service.IDataAccessService;
import com.young.common.util.Page;
import com.young.common.util.StringUtils;
import com.young.interfaces.log.annotation.Log;
import com.young.ums.core.ETopic;
import com.young.ums.core.ISubscriber;
import com.young.ums.model.Role;
import com.young.ums.model.RoleUser;
import com.young.ums.model.enums.ERoleTypeEnum;
import com.young.ums.service.IDataAuthService;
import com.young.ums.service.IRoleUserService;
import com.young.ums.util.UmsConstants;
import org.springframework.stereotype.Service;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;

/**
* 角色用户服务实现
* Created by imrookie on 2018-10-9.
*/
@Service("roleUserService")
public class RoleUserServiceImpl implements IRoleUserService,ISubscriber {

    @Resource(name = "dataAccessService")
    IDataAccessService dataAccessService;//数据层服务

    @Resource(name = "dataAuthService")
    IDataAuthService dataAuthService;//数据权限

    private static final Logger logger = LoggerFactory.getLogger(RoleUserServiceImpl.class);

    private static final String MAPPER = "com.young.ums.mapper.roleUser";//mapper的namespace

    //获取数据列表
    @Log("查询角色用户列表")
    @Override
    public List<RoleUser> getList(RoleUser obj) {
        //权限参数处理
        dataAuthService.handleAuthorityParameter(obj);
        return dataAccessService.getList(MAPPER + ".getList", obj);
    }

    //获取数据列表(分页)
    @Log("分页查询角色用户")
    @Override
    public List<RoleUser> getPage(RoleUser obj, Page page) {
        //权限参数处理
        dataAuthService.handleAuthorityParameter(obj);
        return dataAccessService.getList(MAPPER + ".getList", obj, page);
    }

    //查询单条
    @Log("查询角色用户")
    @Override
    public RoleUser get(String id) {
        return dataAccessService.getObject(MAPPER + ".get", id);
    }

    //统计数量
    @Log("统计角色用户")
    @Override
    public int count(RoleUser obj) {
        return dataAccessService.getObject(MAPPER + ".count", obj);
    }

    //修改
    @Log("更新角色用户")
    @Override
    public int update(RoleUser obj) {
        return dataAccessService.update(MAPPER + ".update", obj);
    }

    //批量删除
    @Log("批量删除角色用户")
    @Override
    public int delete(String[] idArr) {
        int i = 0;
        for(String id : idArr){
            i += this.delete(id);
        }
        return i;
    }

    //删除单条
    @Log("删除角色用户")
    @Override
    public int delete(String id) {
        return dataAccessService.delete(MAPPER + ".delete", id);
    }

    /**
     * 删除角色相关的关联关系
     *
     * @param roleId 角色id
     * @return
     */
    @Log("根据角色id删除角色用户关联关系")
    @Override
    public int deleteByRoleId(String roleId) {
        return dataAccessService.delete(MAPPER + ".deleteByRoleId", roleId);
    }

    /**
     * 删除用户相关的关联关系
     *
     * @param userId 用户id
     * @return
     */
    @Log("根据用户id删除角色用户关联关系")
    @Override
    public int deleteByUserId(String userId) {
        return dataAccessService.delete(MAPPER + ".deleteByUserId", userId);
    }

    //插入
    @Log("插入角色用户关系")
    @Override
    public int insert(RoleUser obj) {
        if (StringUtils.isBlank(obj.getId())){
            obj.setId(CommonUtil.getUUID());
        }
        return dataAccessService.insert(MAPPER + ".insert", obj);
    }

    //批量插入
    @Log("批量插入角色用户关系")
    @Override
    public int batchInsert(List<RoleUser> list) {
        int i = 0;
        for(RoleUser item : list){
            i += this.insert(item);
        }
        return i;
    }

    /**
     * 当角色和用户不存在关联时执行插入
     *
     * @param roleId 角色id
     * @param userId 用户id
     * @return
     */
    @Log("插入角色用户关系当关系不存在时")
    @Override
    public int insertWhenNotHasRelevance(String roleId, String userId) {
        if (this.isRelevanced(roleId, userId)){
            logger.info("[插入角色用户关联(仅当不存在关联时)] 角色[{}]与用户[{}]已经存在关联关系,跳过,不执行插入.", roleId, userId);
            return 0;
        }
        RoleUser roleUser = new RoleUser();
        roleUser.setRoleId(roleId);
        roleUser.setUserId(userId);
        //插入关联关系
        return this.insert(roleUser);
    }

    /**
     * 批量关联用户(N)到角色(1)
     *
     * @param roleId 角色id
     * @param userIds 用户id数组
     * @return
     */
    @Log("批量关联用户(N)到角色(1)")
    @Override
    public int relevanceUsers2Role(String roleId, String[] userIds) {
        int i = 0;
        if (StringUtils.isNotBlank(roleId) && userIds != null && userIds.length > 0){
            for (String userId : userIds){
                i += this.insertWhenNotHasRelevance(roleId, userId);//插入关联关系
            }
        }
        return i;
    }

    /**
     * 批量关联角色(N)到用户(1)
     *
     * @param userId  用户id
     * @param roleIds 角色id数组
     * @return
     */
    @Log("批量关联角色(N)到用户(1)")
    @Override
    public int relevanceRoles2User(String userId, String[] roleIds) {
        int i = 0;
        if (StringUtils.isNotBlank(userId) && roleIds != null && roleIds.length > 0){
            for (String roleId : roleIds){
                i += this.insertWhenNotHasRelevance(roleId, userId);//插入关联关系
            }
        }
        return i;
    }

    /**
     * 删除角色用户关系
     *
     * @param roleId 角色id
     * @param userId 用户id
     * @return
     */
    @Log("根据角色和用户删除角色用户关系")
    @Override
    public int removeRoleUser(String roleId, String userId) {
        RoleUser roleUser = new RoleUser();
        roleUser.setRoleId(roleId);
        roleUser.setUserId(userId);
        return dataAccessService.delete(MAPPER + ".deleteByRoleIdAndUserId", roleUser);
    }

    /**
     * 判断指定角色和用户是否已经关联
     * @param roleId 角色id
     * @param userId 用户id
     * @return
     */
    @Log("判断指定角色和用户是否已经关联")
    @Override
    public boolean isRelevanced(String roleId, String userId) {
        RoleUser roleUser = new RoleUser();
        roleUser.setRoleId(roleId);
        roleUser.setUserId(userId);
        return this.count(roleUser) > 0;
    }

    /**
     * 根据用户id查询用户拥有的角色数组
     *
     * @param userId
     * @return 无结果时返回null
     */
    @Log("根据用户id查询用户拥有的角色id数组")
    @Override
    public String[] getRoleIdsByUserId(String userId) {
        List<String> list = dataAccessService.getList(MAPPER + ".getRoleIdsByUserId", userId);
        if (list != null && list.size() > 0){
            return list.toArray(new String[]{});
        }
        return null;
    }

    /**
     * 根据角色id查询关联的用户数组
     *
     * @param roleId 角色id
     * @return 无结果时返回null
     */
    @Log("根据角色id查询关联的用户id数组")
    @Override
    public String[] getUserIdsByRoleId(String roleId) {
        List<String> list = dataAccessService.getList(MAPPER + ".getUserIdsByRoleId", roleId);
        if (list != null && list.size() > 0){
            return list.toArray(new String[]{});
        }
        return null;
    }

    /**
     * 查询用户拥有的管理员角色
     *
     * @param userId 用户id
     * @return
     */
    @Log("查询用户拥有的管理员角色")
    @Override
    public List<Role> getAdminRoleListByUserId(String userId) {
        if (StringUtils.isBlank(userId)){
            throw new BaseException("用户编号无效");
        }
        RoleUser roleUser = new RoleUser();
        roleUser.setUserId(userId);
        Role role = new Role();
        //管理类型角色
        role.setType(ERoleTypeEnum.ADMIN.type);
        roleUser.setRole(role);
        List<RoleUser> list = this.getList(roleUser);
        List<Role> roleList = null;
        if (list != null && list.size() > 0){
            roleList = new ArrayList<Role>(list.size());
            for (RoleUser ru : list){
                roleList.add(ru.getRole());
            }
        }
        return roleList;
    }

    /**
     * 返回订阅的主题数组
     */
    @Override
    public ETopic[] topics() {
        //订阅用户删除和角色删除主题
        return new ETopic[]{ETopic.ROLE_DEL, ETopic.USER_DEL};
    }

    /**
     * 消费
     *
     * @param topic   主题
     * @param message 传输对象
     */
    @Override
    public void consume(ETopic topic, Object message) {
        try {
            if (topic == ETopic.ROLE_DEL){
                this.deleteByRoleId(message.toString());
            }else if (topic == ETopic.USER_DEL){
                this.deleteByUserId(message.toString());
            }
        } catch (Exception e) {
            logger.info("[UMS消息消费-RoleUserServiceImpl] 消费异常,主题={},消息={}", topic, message, e);
            throw new BaseException(e);
        }
    }
}